


#include <Timer.h>
#include "CausalChat.h"
#include <message.h>

#include <stdio.h>

module CausalChatC {
  uses interface Boot;
  uses interface Leds;
  uses interface Rco;
  uses interface UartByte;
  uses interface UartStream;
  uses interface StdControl;
  uses interface Timer<TMilli> as UART_Timer0;

}
implementation {

  uint16_t counter;
  message_t pkt;
  volatile bool uart_busy = FALSE;
  uint8_t leds = 0;

  char terminal_msg[20];
  int terminal_msg_counter = 0;
  bool terminal_msg_in = FALSE;


  void uart_print(char * string, uint16_t len)
  {
    volatile bool busy = TRUE;

    while(busy)
    {
      atomic{ busy = uart_busy; }
    }
    atomic { uart_busy = TRUE; }
    call UartStream.send((uint8_t *)string,len);

  }


  /* sends a formatted string with src: m and a trailing newline 
   * src is allowed between 0 and 9, otherwise X will be printed
   * s can be max 20 chars long incl. trailing 0 
  */
  void uart_print_msg(uint8_t src, uint8_t msg_len, uint16_t v_clk, char * s)
  {
    char src_string;
    char vc_string[6]; /* 16bit incl TZ */

    if(src > 9)
    {  src_string = 'X'; }
    else
    { src_string = (char) (src + 0x30); }

    snprintf(vc_string, 5, "%d", v_clk);
    
    uart_print("RECEIVED from ", 9);
    uart_print(&src_string,1);
    uart_print(" with VC ", 9);
    uart_print(vc_string, 5);
    uart_print(": ",2);
    uart_print(s, msg_len);
    uart_print("\n",1);

  }



  void setLeds(uint8_t val) {
    if (val & 0x01)
      call Leds.led0On();
    else 
      call Leds.led0Off();
    if (val & 0x02)
      call Leds.led1On();
    else
      call Leds.led1Off();
    if (val & 0x04)
      call Leds.led2On();
    else
      call Leds.led2Off();
  }



  event void Boot.booted() {
    call Rco.init();

    call UART_Timer0.startPeriodic(100);
    call StdControl.start(); /* serial init */
    call UartStream.enableReceiveInterrupt();
    uart_print("\n",1);
    uart_print("input: ",7);
    setLeds(0x07);

  }


  async event void UartStream.receivedByte(uint8_t byte)
  {
    atomic {
      if(!terminal_msg_in)
      {
        terminal_msg[terminal_msg_counter] = byte;
        terminal_msg_counter++;
#if defined(UART_ECHO)
        uart_print((char *)&byte,1);
#endif
        if(byte == 0xD || terminal_msg_counter == MSG_LENGTH-1) /* max len or CR */
        {
          terminal_msg[terminal_msg_counter] = (char)0;
          terminal_msg_in = TRUE;
          return;
        }

      }
    }

  }

  async event void UartStream.receiveDone(uint8_t * buf, uint16_t len, error_t error) {}

  async event void UartStream.sendDone(uint8_t * buf, uint16_t len, error_t error)
  {
    atomic { uart_busy = FALSE; }
  }

  event void UART_Timer0.fired()
  {
    
    atomic {
      if(terminal_msg_in)
      {
        terminal_msg_in = FALSE;
        call Rco.broadcast( (uint8_t*) terminal_msg, terminal_msg_counter);
        terminal_msg_counter = 0;      
        uart_print("input: ",7);
      }
    }  
  }


  event void Rco.deliver(uint8_t nodeid, uint8_t msg_len, uint16_t v_clk, char * msg)
  {
    uart_print_msg(nodeid, msg_len, v_clk, msg);  
  }


}
